package no.uio.inf5750.wsclient.javarosaclient;

import java.util.Hashtable;

import javax.microedition.midlet.MIDlet;

import org.javarosa.core.Context;
import org.javarosa.core.JavaRosaServiceProvider;
import org.javarosa.core.api.Constants;
import org.javarosa.core.api.IActivity;
import org.javarosa.core.api.IShell;
import org.javarosa.core.api.IView;
import org.javarosa.core.util.WorkflowStack;

/**
 * Shell for a DHIS midlet. Based on the demo-shell.
 */
public class SimpleJRShell
    implements IShell
{
    MIDlet midlet;

    WorkflowStack stack;
    Context context;

    IActivity currentActivity;

    public SimpleJRShell()
    {
        stack = new WorkflowStack();
        context = new Context();
    }

    public void exitShell()
    {
        midlet.notifyDestroyed();
    }

    public void run()
    {
        workflow( null, null, null );
    }

    /* (non-Javadoc)
     * @see org.javarosa.shell.IShell#activityCompeleted(org.javarosa.activity.IActivity)
     */
    public void returnFromActivity( IActivity activity, String returnCode, Hashtable returnVals )
    {
        workflow( activity, returnCode, returnVals );
    }

    private void workflow( IActivity lastActivity, String returnCode, Hashtable returnVals )
    {
        if ( returnVals == null )
            returnVals = new Hashtable(); // for easier processing

        if ( lastActivity != currentActivity )
        {
            System.out.println( "Received 'return' event from activity other than the current activity"
                + " (such as a background process). Can't handle this yet" );
            return;
        }

        if ( returnCode == Constants.ACTIVITY_SUSPEND || returnCode == Constants.ACTIVITY_NEEDS_RESOLUTION )
        {
            stack.push( lastActivity );
            workflowLaunch( lastActivity, returnCode, returnVals );
        }
        else
        {
            if ( stack.size() > 0 )
            {
                workflowResume( stack.pop(), lastActivity, returnCode, returnVals );
            }
            else
            {
                workflowLaunch( lastActivity, returnCode, returnVals );
                if ( lastActivity != null )
                    lastActivity.destroy();
            }
        }
    }

    private void workflowLaunch( IActivity returningActivity, String returnCode, Hashtable returnVals )
    {
        if ( returningActivity == null )
        {
            launchActivity( new WelcomeActivity( this ), context );
        }
        else if ( returningActivity instanceof WelcomeActivity )
        {
            String returnVal = (String) returnVals.get( WelcomeActivity.CMD_KEY );
            if ( returnVal == WelcomeActivity.CMD_EXIT )
            {
                exitShell();
            }
            else if ( returnVal == WelcomeActivity.CMD_DATASET_ADDUPDATE )
            {
                context.setElement( "selected activity name", "Add/Update dataset" );
                launchActivity( new NotImplementedActivity( this ), context );
            }
            else if ( returnVal == WelcomeActivity.CMD_DATASET_SIMPLIFIED_ADDUPDATE )
            {
                context.setElement( "selected activity name", "Simplified add/update dataset" );
                launchActivity( new NotImplementedActivity( this ), context );
            }
        }
    }

    private void workflowResume( IActivity suspendedActivity, IActivity completingActivity, String returnCode,
        Hashtable returnVals )
    {
        // default action
        Context newContext = new Context( context );
        newContext.addAllValues( returnVals );
        resumeActivity( suspendedActivity, newContext );
    }

    private void launchActivity( IActivity activity, Context context )
    {
        currentActivity = activity;
        activity.start( context );
    }

    private void resumeActivity( IActivity activity, Context context )
    {
        currentActivity = activity;
        activity.resume( context );
    }

    public boolean setDisplay( IActivity callingActivity, IView display )
    {
        if ( callingActivity == currentActivity )
        {
            JavaRosaServiceProvider.instance().getDisplay().setView( display );
            return true;
        }
        else
        {
            // #if debug.output==verbose
            System.out.println( "Activity: " + callingActivity + " attempted, but failed, to set the display" );
            // #endif
            return false;
        }
    }

    public void setMIDlet( MIDlet midlet )
    {
        this.midlet = midlet;
    }

}
